//
//  Utilities.swift
//  Link
//
//  Created by melvyn on 2018/9/6.
//  Copyright © 2018 NEET. All rights reserved.
//

import Foundation
import ObjectiveC.runtime

extension UIApplication {
    public var mainAppWindow: UIWindow? {
        guard let window = delegate?.window else {
            return keyWindow
        }
        return window
    }
}

extension UIButton {
    
    private struct Key {
        static var handler = "akii.me.button.handler.runtime.key"
    }
    private var handlers: [Any] {
        set {
            objc_setAssociatedObject(self, &Key.handler, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        get {
            guard let result = objc_getAssociatedObject(self, &Key.handler) as? [Any] else {
                self.handlers = []
                return []
            }
            return result
        }
    }
    
    public func addEventHandler(_ handler: @escaping (UIButton) -> Void, for event: UIControl.Event) {
        handlers.append(handler)
        addTarget(self, action: #selector(eventHandler(_:)), for: event)
    }
    
    public func addEventHandler(_ handler: @escaping () -> Void, for event: UIControl.Event) {
        handlers.append(handler)
        addTarget(self, action: #selector(eventHandler(_:)), for: event)
    }
    
    @objc private func eventHandler(_ sender: UIButton) {
        handlers.forEach {
            if let handler = $0 as? (UIButton) -> Void {
                handler(sender)
            } else if let handler = $0 as? () -> Void {
                handler()
            }
        }
    }
}

public protocol NibLoadable {
    static func nibNameAndBundle() -> (String, Bundle)
}

public extension NibLoadable where Self: UIViewController {
    
    static func nibNameAndBundle() -> (String, Bundle) {
        
        let bundle = Bundle(for: Self.self)
        
        // note: nib file must have the same name as the view controller class
        let nibName = (String(describing: type(of: self)) as NSString).components(separatedBy: ".").first!
        
        return (nibName, bundle)
    }
}
